package com.dahua;

/**
 * @author chen_MingLiang
 * @version 1.0
 * @date 2020/1/26 16:29
 */

import com.dahua.service.BeanService;
import org.springframework.beans.factory.support.RootBeanDefinition;

/**
 * 这里是笔记
 */
public class ImportantDefinition {

	/**
	 * 一
	 */
	//1.bean  被spring容器管理,具有完整的生命周期.对象:只是一个普通的对象而已.
	//2.spring扫描项目,把符合扫描规则的类去实例化,有些是肯定不符合规则的 比如@DepandsOn 这个注解的意思是 要实例化某个类,必须先实例化@DepandsOn这个类,还有就是原型的类,原型类是在用的时候才被实例化的.lazy的也是不能被实例化的.还有Abstract类的也不行.
			//2.1所以spring 实例化的时候 肯定会做一个validate(info)验证,验证之前肯定要解析 parse(类),
			//2.2所以生命周期 scan ---parse(beanDefinitionMap.put) ---validate(这个过程中可以插手,通过后置处理器,改变beanDefinition)---实例化(遍历map得到beanDefinition)---初始化---(生命周期)
	//3.beanDefinition:spring当中的class. 是spring对于一个bean表述.beanDefinition中所有的属性都可以在xml中找到与之对应的标签,都是可以配置的
			//spring 刚出来的时候是用beanDefinition来配置的,并不是xml.所以xml里面都是可以对beanDefinition中每一个属性进行配置的.
	//4.spring容器:
			//4.1 ioc.getBean()-->singletonObjects---这是DefaultSingletonRegistry类中的一个concurrentHashMap
			//ioc.getBean() == this.singletonObjects.get(beanName);但是 注意,容器并不等于map,应该说map<容器.单例池==map.因为容器不止一个map
			//存beanDefinition的Map --beanDefinitionMap
			//spring容器--->可以理解为一个applicationContext对象.但是从代码的角度来讲,是由各种map和容器,各种后置处理器等等很多组件组成的
	//5.beanDefinition接口继承自AttributeAccessor这个接口,beanDefinition的实现类AbstractBeanDefinition继承自BeanMetadataAttributeAccessor,
			//而这个BeanMetadataAttributeAccessor 是AttributeAccessor的实现类,BeanMetadataAttributeAccessor中有个setAttribute方法调用的
			// 是父类AttributeAccessorSupport的setAttribute方法,这个setAttribute是什么意思?这AttributeAccessorSupport里面维护了一个人map
			//叫做private final Map<String, Object> attributes = new LinkedHashMap<>();这是用来存放对beanDefinition的描述.也就是说,beanDefinition是用来描述bean的,而这个类是用来描述beanDefinition的
			//子路的意思是 用来存beanDefinition的元数据,(注解),
			// 也就是说AttributeAccessor这个接口是提供对beanDefinition元数据操作的API,实现是由AbstractBeanDefinition来实现,在他的父类BeanMetadataAttributeAccessor里面维护了一个map
			//5.1 beanDefinition继承自BeanMetadataElement这个接口,这个接口是用来描述bean的元.就相当于类是用class来描述,谁来描述class-->文件.同理:这个是用来描述bean的元
			//这里面只有一个方法,getSource(),同样在beanDefinition.getSource是由父类BeanMetadataAttributeAccessor来维护的.
			//这个getSource()得到的是这个类所在的磁盘上的路径
			//总结:BeanMetadataAttributeAccessor这个类是对beanDefinition两个父类接口(AttributeAccessor, BeanMetadataElement )的统一实现


	/**
	 * 二 beanDefinition后半部分
	 */
	//AbstractBeanDefinition--有以下三个子类,存在的意义是为了让别人去继承我.那么它在beanDefinitionMap当中是不需要设置Class的,因为它不会被实例化
	//因为以前没有xml的时候都是java代码去创建beanDefinition,那么很多代码都是重复的 什么懒加载啊这些单例啊,都是一样的,所以要创建一个通用的模板,所以就存在这个AbstractBeanDefinition
	//6.GenericBeanDefinition----通用bean定义.比下面两者有优势,下面两者有很大局限性
			//所有在xml中定义的bean,拿出来的都是genericBeanDefinition
			//ChildBeanDefinition---在spring2.5的时候首选,没有GenericBeanDefinition这个玩意
					//很大的局限性:这个parentName是通过构造方法来传入的.初衷是这个ChildBeanDefinition只能作为子bd,不能单纯描述一个bean,必须是子bd
			//RootBeanDefinition----一般是作为父bd出现,或者真实bd出现,不能作为子bd出现.所以出现了ChildBeanDefinition.如果给它设置父bd,它本身变成子bd,就会抛异常
			//2.5之后,推出了GenericBeanDefinition,可以完全替代ChildBeanDefinition
			RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
			public void test(){
				//rootBeanDefinition.getPropertyValues()这是个集合
				rootBeanDefinition.getPropertyValues().add("name","zl");//当BeanService被实例化的时候,属性是来自这里
				rootBeanDefinition.setBeanClass(BeanService.class);
//				rootBeanDefinition.setAbstract(true);//这个可以设置为true,他就不会被实例化,可以不设置BeanClass
//				ChildBeanDefinition childBeanDefinition = new ChildBeanDefinition("bs");
//				childBeanDefinition.setBeanClass(IndexService.class);
//				ioc.registerBeanDefinition("bs",rootBeanDefinition);
//				ioc.registerBeanDefinition("cs",childBeanDefinition);
			}
			//ConfigurationClassBeanDefinition --继承自RootBeanDefinition
			//AnnotatedGenericBeanDefinition ---继承自GenericBeanDefinition
			//ScannedGenericBeanDefinition---继承自GenericBeanDefinition
	 //7.spring解析属性放到genericBeanDefinition.getPropertyValues();中.
	    	// <bean id ="xx" class = "com.dahua.luban">
			//	<constructor-arg value = "xxx" index = "0"></constructor-arg>
			//	<constructor-arg value = "xxx" index = "1"></constructor-arg>
			//</bean>
			//7.1spring的依赖检查..不是很重要


	/**
	 * 三.扩展扫描规则
	 */
	//8.beanFactoryPostProcessor,bean工厂的后置处理器,顾名思义--干预bean工厂(DefaultListableBeanFactory)的工作流程.
			//8.1父类无参构造AnnotationConfigApplicationContext extends GenericApplicationContext
						//public GenericApplicationContext() {
			//		this.beanFactory = new DefaultListableBeanFactory();
			//	}
			//这个DefaultListableBeanFactory就是我们代码级别所说的bean工厂,beanDefinitionMap就存在于我们的这个bean工厂当中
			//8.2	BeanFactoryPostProcessor(在子接口完成之后执行,这个方法里面完成了CGLIB代理)-->子接口BeanDefinitionRegistryPostProcessor(spring还没有完成扫描之前执行)--实现类ConfigurationClassPostProcessor(这个类非常关键,完成了扫描,它完成了上面两个接口的两个方法)
					//BeanFactoryPostProcessor 动态修改bean工厂,动态注册一个类
					//一般我们只扩展BeanFactoryPostProcessor,不扩展BeanDefinitionRegistryPostProcessor,因为BeanDefinitionRegistryPostProcessor执行时机更早,更加底层,用不到

			//补充://BeanDefinitionRegistryPostProcessor类的这个方法就是把所有扫描出来的类变成beanDefinition放到map当中,由他的唯一子类ConfigurationClassPostProcessor去实现
					//	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
	/**^^^^^^^^^^^^^^^^^^^^^^^^最重要的方法,没有之一^^^^^^^^^^^^7&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
			/**这个void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;方法是spring当中最重要的方法,没有之一*/

	//9 @MapperScan 和mybatis集成原理
			//扫描原理:自己手动写的mvc一样的扫描原理.
					// spring当中的 classPath:xxx.class.--->就相当于我们文件中的file:\\\d:\xx\xx.class,是一样的.spring中一切皆为Resource.后面会具体讲Resource.spring对其做了扩展
					//也就是说在spring眼中,给我一个classPath,就相当于给我一个URL.为什么要这样?因为spring认为URL功能不够丰富,所以做了很多功能扩展
		//9.1扫描会做两个判断:1.注解是否符合条件.2.是否合理.就是那4个判断,是否是独立的,是否是抽象,是否是LookUp....
							//这里就解释了 为什么我们在接口上加@Cpmponent不会被扫描进来
		//includeFilters 是什么时候被初始化的?因为spring扫描和我们自己写的扫描 ,其他地方都是一样的,只有这个includeFilters是提前被初始化好的.我们要找到这个关键点
					//通过idea的find use 可以看到是通过scan.add()方法添加进去的,而这个scan对象就是ClassPathBeanDefinitionScanner,那么我们如果要自己往这个-->
					//-->includeFilters添加规则,那么我们自己可以写一个类A,去继承ClassPathBeanDefinitionScanner,然后自己调用A.add();
					//看AnnotationConfigApplicationContext中的 this.scanner = new ClassPathBeanDefinitionScanner(this);点源码查看什么时候初始化的
		//9.2扩展原理,自己写一个扩展扫描器,然后往includeFilters添加自己的注解--步骤:--->
					//--->1.写一个类继承它.CustomScanner extends ClassPathBeanDefinitionScanner
					//--->2.添加一个自己的注解MyComponent.class
					// 		CustomScanner customScanner = new CustomScanner(ioc);
					//		customScanner.addIncludeFilter(new AnnotationTypeFilter(MyComponent.class));
					//		int count = customScanner.scan("com.dahua");

	/**
	 * 四:spring 启动流程--ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry
	 * 扫描beanDefinition过程1-->BeanDefinitionRegistryPostProcessor完成扫描
	 */
	//10.Mybatis如何将一个个beanDefinition放入容器的?@MapperScan-->@Import(MapperScannerRegistrar.class)-->doScan-->返回Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
			//lassPathMapperScanner extends ClassPathBeanDefinitionScanner 所以执行doScan的时候,可以直接调用父类的doScan方法,调用父类的doScan方法,这个父类是spring的类,扫描进去后直接加到beanDefinitionMap里面去了(在DefaultListableBeanFactory这个类里put)
			//TODO 什么时候实例化这个interface代理对象的?
	//11.新版Mybatis
		//ConfigurationClassPostProcessor-->继承自BeanDefinitionRegistryPostProcessor-->继承自BeanFactoryPostProcessor-(这是干预bean工厂的初始化过程,不是实例化)
																							//在应用程序上下文的标准初始化之后修改它的内部bean工厂
		//先执行BeanDefinitionRegistryPostProcessor(这里也分为两个步骤.两个Ordered接口),再执行BeanFactoryPostProcessor-->
		//-->invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);这行代码里面完成了解析,
		//说明:@Service注解里面包含了@Component,那么我们认为@Service继承了@Component.同理@MapperScan包含@Import,我们认为@MapperScan继承了@Import
				//注意:@Import可以引入一个普通类,还可以引入一个Registrar,这两个spring是分开处理的,@MapperScan就是引入的registrar.
				//会把所有的ImportBeanDefinitionRegistrar放入一个map,到parse方法后面执行
				//Mybatis中,最新版本中,MapperScanConfigurer实现了BeanDefinitionRegistryPostProcessor这个底层接口,和spring内部同期执行.老版本没有的
				//老版本是直接new一个ClassPathScanner 来扫描了.
				//老版本中,MapperScanRegistrar实现了ImportBeanDefinitionRegistrar,所以这个类会放入到map,后面一起会被执行.当后面循环遍历执行的执行,mybatis就new了一个ClassPathScanner 来扫描-->
				//-->所有的Dao,变成beanDefinition放入到bdMap中
				//新版本中,MapperScanConfigurer实现了BeanDefinitionRegistryPostProcessor这个底层接口,和spring内置的扫描同期执行,相当于扫描时间提前了
		//老版本中:执行到invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);这行代码的时候-->
		// -->会执行:@MapperScan中@Import的那个MapperScannerRegistrar类的registrarBeanDefinitions()方法--->
		//-->这个方法一进来就会new一个ClassPathScanner,去doScan,在这里把DAO变成了beanDefinition,后面给spring去new
		//新版本中,直接添加了一个MapperScannerConfigurer 放入bdMap中,这个类实现了BeanDefinitionRegistrarPostProcessor接口,重写了BeanDefinitionRegistrarPostProcessor-->
		//-->的postProcessBeanDefinitionRegistry()方法,我们知道这个方法就是扫描的方法.所以,他会自动去扫描.嗯ok
	//12.spring扫描配置类,处理注解的地方:ConfigurationClassParser这个类里.


	/**
	 * 五.ConfigurationClassPostProcessor.postProcessBeanFactory()--->判断是否需要CGLIB代理以及CGLIB代理完成单例逻辑
	 * spring启动流程
	 */
	/**
	 * bean工厂后置处理器执行流程:
	 * 		1.先执行BeanDefinitionRegistrarPostProcessor
	 * 	    	先执行程序员通过API提供的ioc.addBeanFactoryPostProcessor()
	 * 		   然后执行spring内置的BeanDefinitionRegistrarPostProcessor和程序员提供的有特点的BeanDefinitionRegistrarPostProcessor(比如实现了Ordered接口的就是有特点的)
	 * 		   最后执行程序员配置的提供的没有任何特点的BeanDefinitionRegistrarPostProcessor
	 * 		   以上执行的 都是BeanDefinitionRegistrarPostProcessor这个子类独有的方法postProcessBeanDefinitionRegistry(xxx);
	 *
	 * 		2.执行BeanFactoryPostProcessor
	 * 			先执行实现了BeanDefinitionRegistrarPostProcessor类的BeanFactoryPostProcessor这个父类的方法postProcessBeanFactory(xxx);
	 * 			再执行只实现了BeanFactoryPostProcessor的这个父类方法---也是分特点的(如实现了Ordered接口的就是有特点的)
	 */
	///**从62行set集合开始到这里为止,完成了  扫描类--put-dbMap--解析--AppConfig----@Configuration---map()full,little的工作.准备工作就-->
	// -->绪.那么下面要干嘛了??*/
	//按理说要实例化对象了,因为bdMap都已经准备就绪了.但是---我们实例化对象还要考虑实例化什么对象
	//实例化对象有几种方式??1.new 2.反射 3.序列化 4.克隆
	//我们如果在某个类上加一个@Component注解,那么spring给我们实例化对象,我们根本不能控制我们要实例化什么样的bean-->
	//-->@Bean就可以 因为我们在@Bean方法内部自己写return new Object();或者代理对象等等...spring肯定调用了我们被@Bean注解的方法
		//测试:创建E,F类,测试类TestEF.可见EF类都是单例的.但是 如果我在f方法里面调用e方法,就会打破单例.但是--->
		//--->这个情况肯定是spring不允许的,我们如果在AppConfig类上加上@Configuration注解,那么就不会产生这个情况了.那么我们要思考为什么呢?-->
			//-->我们知道程序是肯定不会骗人的,它代码写在那里,就是在那里,按理说在f方法里就要被调用,但是不打印e init了 就是没有被调用.那么我们认为应该是代码被修改掉了,程序是不会出错少调用代码的
			//-->那么或者说 f()方法可能被代理被修改了导致e()方法不被执行.回到上面的扫描类--put-dbMap--解析--AppConfig----@Configuration---map(),那么现--->
			// -->在我们认为准备工作都做好了,dbMap都就绪了,要去实例化对象了,那么到底是new什么样的对象?AppConfig?要不要被代理?
			//实际上,加了@Configuration,就是个代理对象.不加就是个正常bean
		//得出一个结论:任何一个类都可以成为一个配置类,并不一定要加@Configuration,那为什么要加@Configuration呢?为了保证AppConfig类是个代理对象.如果不是-->
		//-->代理对象,那么如果在@Bean方法里面互相调用,那么就会导致产生多个bean,会产生多例bean,保证不了单例.会打破spring的单例原则
		//被@Bean描述的bean,他的beanDefinition里面对应的beanClass为null,为什么?因为@Bean描述的是个方法,那么方法的返回值我可以是个接口,但是里面return new的时候-->
		//-->我可以new一个实现类出来,所以它这里不方便描述
	//13.spring判断一个bean是否正在被创建!--
		//   @Bean这种类型的bean被创建的时候,会将这个方法比如e()方法一个ThreadLocal<Method>里面,当创建完成的时候,会移除.-->
		//-->@Component这种bean类型的bean被创建的时候,会将beanName放到一个集合里面,当这个bean创建完成,会从集合中移除.
		//spring如何解决AppConfig中->f()中调用e()?就是判断当前执行的方法是否已经存在于那个集合里面(正在创建的bean的方法),并且两者是否相同.如果相同,直接调用父类的(AppConfig f()),new F(),f被创建-->
		//-->但是这里会进到e(),e()方法现在不在创建bean的集合里面 ,那么就不是正在创建bean的方法,两者不相等,那么会执行自己的e(),把E new出来.这就是代理来实现单例.-->
		//-->具体见ConfigurationClassEnhancer这里的代码359行


	/**
	 * 六:spring循环引用--循环依赖
	 */
	//14.spring循环依赖的条件:1.单例 2.setter注入,不能构造注入
	//15.spring可以关闭循环依赖 :ioc.getBeanFactory-->DefaultListenerBleBeanFactory.setAllowCircularReference(false)
			//研究循环依赖,必不可少研究属性注入.因为依赖就是注入或者DI,研究属性注入,必须知道他在什么时候注入,模拟大致的spring的bean的生命周期
				//列个大概:
				//-------1.推断构造方法
				//-------2.实例化对象
				//-------3.属性注入
				//-------4.lifeCycle回调初始化方法
				//-------5.AOP
							//spring创建bean大致流程-->beanFactory.preInstantiateSingletons();-->
							//-->Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);一路进去...
							//所有验证通过,再次判断容器中有没有,没有 就创建bean
							//protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
				//最终会走到一个getBean()
		//为什么公用一个getBean()??循环引用
		//第一次调用后置处理器--和AOP有关
		// AbstractAutowireCapableBeanFactory-->Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		/**判断是否允许循环依赖*/
		//boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			//				isSingletonCurrentlyInCreation(beanName));
		//循环依赖的时候,先去getBean()那OrderService,当判断到需要属性注入,他会去getBean()拿UserService();-->
		//-->注意,这个时候,正在创建的那个Set集合(singletonCurrentlyInCreation)当中就有了两个beanName.
		//-->这个时候,走到了OrderService中的UserService中的属性填充,又要走一次生命周期.--->
		//-->问题来了UserService属性注入的时候需要找OrderService--->这一次又要getSingleton()-OrderService
/**关键来了*/		//关键来了,这个时候容器中(单例池)拿OrderService还是空,那么走下面的判断
		////当OrderService需要注入UserService,创建UserService的时候又要注入OrderService,这个时候,因为两个bean都在被创建,那么都会放进正在被创建的bean的set集合-->
		//		//-->并且singletonObject单例池中拿不到OrderService,那么下面这个条件满足.所以,下面开始去创建OrderService,这一次,这个条件就会被满足,就会进里面的逻辑,-->
		//		//-->spring在这里完成了循环依赖.关键是这个正在被创建的集合.

	//16.spring bean的一级二级三级缓存
		//一级缓存:singletonObjects Map
		//二级缓存:singletonFactories  Map--->属性注入的时候,可以完成AOP.因为如果不注入一个工厂,如果UserService和OrderService都需要AOP,那么必然有一个不能完成AOP功能,只有简单功能.只有注入了一个工厂,工厂可以生产出一个完整生命周期的bean
					//A--new --属性B(A还是一个简单对象,没有代理)--getB--new B----需要属性A---getAFactory(很关键,产生完整生命周期的bean包括AOP)--A注入到B--B被put到容器--生命周期回调--AOP---full A--放到容器
		//三级缓存:earlySingletonObjects Map


	/**
	 * 七:AOP原理一.
	 */
	//17.spring bean后置处理器:beanPostProcessor,干预bean的产生过程(实例化和初始化)包括自定义的后置处理器.AOP就是通过bean后置处理器来完成的
			//aop完成代理就是BeanPostProcessor的postProcessAfterInitialization()来完成的.aop demo中自己模拟实现了一个cglib实现的aop
			//aop 概念-->
					//1.AspectJ-->切面--->是一个综合体
					//2.Join Point-->连接点--->AOP代理某个类中的某个方法就是一个连接点-->连接点是AOP中颗粒度最小的单位
					//3.pointCut -->切入点-->某一类型连接点的集合,比如-->
							//-->找出 A B C 三个类中为public 的第一个参数为 String类型的 方法,可能找出2个 --2个连接点构成一个切入点
							//-->找出A B C 三个类中为public 的 只要参数为String 类型的方法  可能找出三个-->3个连接点构成一个切入点
							//-->再通俗来讲,连接点中是data,切入点则是table,data存在table中
					//4.advice-->通知
							//1.逻辑-->打印一句话
							//2.执行时机-->打印在方法之前还是之后
					//5.target-->目标对象
					//6.proxy-->代理对象
					//7.weaving-->织入-->将advice应用到pointCut的过程,就叫织入
	//18.springAOP和AspectJ
			//AOP 是一种变成规范,springAOP和AspectJ都是对AOP变成标准的实现
			//早期的时候springAOP语法格式非常晦涩,并且他产生代理类是在运行时产生的,不太友好
			//AspectJ比较优秀,它产生代理类是在编译时就产生
		//所以,springAOP后来将AspectJ编程风格引入到spring
		//18.1那么如何使用AspectJ这个语法?
			//加注解@EnableAspectAutoProxy或者<aop:aspect-autoProxy>
			//声明一个切面类 demo中为aop包中的AspectJ,放入容器,加上@AspectJ注解
			//切面类中生命切入点,连接点和通知
			//我们自定义了一个Spring模拟cglib代理,实现了BeanFactoryPostProcessor的after....()方法,这个方法就是实现AOP的.
		//以上就是aop的概念和AspectJ的风格


	/**
	 * 八:AOP原理 二
	 */
	//19.spring扫描机制-->磁盘上的class文件:Resource封装类的全路径---File--通过类名获得Class---bd
					//由于这个机制的存在,导致spring在做AOP之前执行第一次后置处理器的时候,必须要做是否是合成类的判断-->isSynthetic()
					//合成类的原理见synthetic包的demo.
	//20.applyBeanPostProcessorsAfterInitialization创建代理对象,完成AspectJ中的连接点的解析,最终会由JDK动态代理或者CGLIB动态代理来完成创建

	/**
	 * 九:spring生命周期之推断构造方法
	 */
	//注入模型:byName,byType,构造方法,No
	//21.推断构造方法:
		//21.1.如果有个类要被注入到容器,加上@Component,如果他有多个构造方法加一个无参默认构造,那么它会执行默认的无参构造-->
		//-->因为这个和注入模型有关,@Component这种注入模型为NO,意思是不自动注入.
		//-->如果用后置处理器修改注入模型为byConstructor,那么它会从多个构造方法中选出一个spring认为是最合理的构造方法来使用
		//-->如果在某个构造方法上加上@Autowired,那么spring就会用这个构造,因为我们手动指定了
		//-->这也证明了@Component,@Autowired是手动装配
		//具体见constructor包里面的注释
	/**
	 * spring推断构造方法
	 * 1.我们现在默认是@Component,这种我们知道不是自动装配,因为注入模型为NO,那么这种情况下,就是不自动注入,不自动注入的话,带参构造里面的参数无法注入,所以spring推断构造方法没用,所以一定会走无参构造,所以推断构造方法那里一定返回null
	 * 2.如果我们在某个构造方法上加入@Autowired,那么也是手动装配,我们是手动指定了某个构造,那么spring推断构造方法就会推断出这个方法
	 * 3.如果我们在3个构造方法上不带任何注解,只留下一个带参构造,那么spring没的选,只能用这个代餐构造,所以会推断出来.1为null是因为不需要,后面用的时候直接拿无参构造即可
	 * 4.如果我们3个构造不带任何注解,但是我们通过BeanFactoryPostProcessor把注入模型改成byConstructor,那么spring会找到他认为最合理的构造方法,并且推断出来,我试了下是最长的构造
	 * 5.如果是手动装配,有带参构造的情况下,必须要写无参构造.否则会报错.如果自动装配,那么不会报错
	 * 6.如果是手动装配,并且在很多构造上加了@Autowired,并且都为required=false,那么会把这些都返回出来
	 * 7.如果是自动装配,提过了多个构造,spring认为构造过于复杂,第一次推断还是返回null,由第二次进入autowireConstructor(beanName, mbd, ctors, args)去判断哪个合理
	 */
	//22.推断构造方法的方法:
			//基于手动装配
			//determineConstructorsFromBeanPostProcessors
			//determineCandidateConstructors,AutowiredAnnotationBeanPostProcessor这个后置处理器来实现,这个和注入模型有关.这里是手动装配
				//提供了两个合格的 会抛异常.
				//如果提供多个模糊的构造方法--那么推断出0个,那么使用默认的
				//如果提供了一个非默认构造,就会推断出来
			//
		//基于自动装配
			//第二次进入autowireConstructor(beanName, mbd, ctors, args)去判断哪个合理,ConstructorResolver这个类中
				//Constructor<?> constructorToUse = null;-->最后被确定出来的构造方法
				//ArgumentsHolder argsHolderToUse = null;-->这里是用来存放构造方法里面参数的值,spring找出来后放到这里
				//Object[] argsToUse = null;最终确定的参数,上面的值要通过这个来构建,看类结构
			//如果找到同样权重的构造,有个宽松匹配的配置,默认为true.可以配置.如果配置为false,这会抛异常


	/**
	 * 十:spring生命周期之推断构造方法之  构造属性注入
	 */
	//argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
	//								getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
	//添加一个Supplier.这样的话在推断构造方法的时候,如果我们是手动注入,并且有两个有参构造,并且没有提供无参构造,也不会报错.跟factoryMethod一样
	//	beanService.setInstanceSupplier(()->new OrderService());


	/**
	 * 十一:应用合并后的BeanDefinition
	 */
	//23.BeanDefinition:
				//1.ScannnerBd
				//2.Annotated bd
				//3.Generic bd
				//4.Root bd
		//23.1-->spring从.java文件--->beanDefinition-->bean经历完整的生命周期中,一定会走一个beanDefinition,但是这个beanDefinition不是上面
		//-->任何一个,是合并后的RootBd,4是没有合并的bd,换言之,MergedBeanDefinition
	//24.为什么要合并Merge,因为每一个bd,就像class一样,也有父类,它会需要父类里面的信息,光拿自己的bd去实例化,信息是不完整的.
		//24.1什么时候合并?开始实例化之前
	//25.合并bd以及合并bd的时机
			//for (String beanName : beanNames) {
		//合并bd,
		//这里合并了后,那么后面实例化的时候就不需要合并了,但是并不是所有的beanDefinition都在这里合并--->
		//-->因为这里是bdrp,我们beanFactoryPostProcessor执行时机是在这个之后.如果我们在那里修改了bd,那又要重新合并
		//-->或者我们可以ImportBeanPostProcessorRegistrar来导入一个beanDefinition,都要合并
		//RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
	//26.合并后的bd还需要在缓存中删除
		// Let the bean definition get re-merged now that we're actually creating
		// the bean... just in case some of its metadata changed in the meantime.
		//将合并后的bd  remove掉.看注释,是因为怕某些操作修改了bd的元数据,
		//所以创建bean的时候要重新合并一次.因为有可能我们通过各种后置处理器对其进行改变
		//clearMergedBeanDefinition(beanName);


	/**
	 *十二:spring生命周期之属性解析
	 */
	//27:解析属性applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
		//这里并未完成填充,只是解析,并且放入缓存,InjectElement包装了信息,放在injectionMetaDataCache缓存当中

	//28.//如果是手动装配,那么我们类里面的setter方法是不生效的
	//		//如果是有注入模型的,AUTOWIRE_BY_NAME或者AUTOWIRE_BY_TYPE,那么我们的setter方法会生效
	//		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
		//也就是说,我们A类里面只要有一个setter方法,不用任何属性,setter方法里面传B,它就会把B注入进来.这就是自动注入.所以@Autowired跟自动注入没有任何关系

	/**
	 * 十三:自动注入:setter
	 */
	//属性填充 populate
	//29.为什么在自动装配的情况下,提供一个set开头的方法,参数如果在spring容器当中,就会自动注入?
		//获取属性的值
			//解析,value就是拿到需要注入的对象
				//					//调用getBean.有则获取,无则创建
				//					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
		//反射填充属性..
			//			if (value != null) {
			//				ReflectionUtils.makeAccessible(field);
			//				field.set(bean, value);
			//			}

	//30.@Autowired //如果有两个及以上类型一样的,就按照名字去匹配
		//根据类型找匹配的bean,有可能找到多个
			//		String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
			//				this, requiredType, true, descriptor.isEager());
			//然后---->matchBeans.size>1 -->根据名字去找
		//				instanceCandidate = matchingBeans.get(autowiredBeanName);

	//31.找到set方法
		////拿到所有的set方法名
			//		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		//mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
			//				//spring找出所有需要解析的属性(方法 set)并没有完成填充
			//				autowireByType(beanName, mbd, bw, newPvs);mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
			//				//spring找出所有需要解析的属性(方法 set)并没有完成填充
			//				autowireByType(beanName, mbd, bw, newPvs);
	//32.调用set方法注入
		//if (pvs != null) {
			//			//把属性值应用上
			//			//程序员手动提供
			//			// 或者spring找出来的那些-自动注入
			//			//会调用set方法
			//			applyPropertyValues(beanName, mbd, bw, pvs);


}
